﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Linq;
using Gmantis.Controls.Automation;

namespace Gmantis.Controls
{
    public delegate void SelectionChangedEventHandler(object sender, SelectionChangedEventArgs e);

    [TemplateVisualState(Name = "Focused", GroupName = "FocusStates"), 
    StyleTypedProperty(Property = "ScrollBarStyle", StyleTargetType = typeof(ScrollBar)), 
    TemplatePart(Name = "Scroll", Type = typeof(System.Windows.Controls.ScrollViewer)), TemplateVisualState(Name = "Valid", GroupName = "ValidationStatesStates"), 
    TemplateVisualState(Name = "InvalidUnfocused", GroupName = "ValidationStatesStates"), 
    TemplateVisualState(Name = "InvalidFocused", GroupName = "ValidationStatesStates"), 
    StyleTypedProperty(Property = "ValidationDecoratorStyle", StyleTargetType = typeof(ValidationDecorator)), 
    TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
    public class TreeView : HierarchicalPresenter
    {
        // Fields
        private TreeViewItem _currentEditItem;
        private DragDropManager _dragDropManager;
        private FrameworkElement _dropArrow;
        private FrameworkElement _dropLine;
        internal System.Windows.Controls.ScrollViewer _elementScroll;
        private IList<WeakReference> _expandedItems;
        private bool _isAppendAction;
        internal bool _isLoaded;
        private bool _isProcessingSelection;
        private bool _isUpdatingExpandedItems;
        private IList<TreeViewItem> _itemList;
        private long _lastKeyTicks;
        private AutomationPeer _peer;
        private string _searchBuffer;
        private RangeSelectionManager _selectionManager;
        private bool _throwSelectionModeChanged;
        public static readonly DependencyProperty AllowDragDropProperty = DependencyProperty.Register("AllowDragDrop", typeof(bool), typeof(TreeView), null);
        public static readonly DependencyProperty AutoScrollModeProperty = DependencyProperty.Register("AutoScrollMode", typeof(AutoScrollMode), typeof(TreeView), new PropertyMetadata(AutoScrollMode.Both));
        public static readonly DependencyProperty AutoSearchProperty = DependencyProperty.Register("AutoSearch", typeof(bool), typeof(TreeView), new PropertyMetadata(true));
        public static readonly DependencyProperty AutoSearchResetDelayProperty = DependencyProperty.Register("AutoSearchResetDelay", typeof(int), typeof(TreeView), new PropertyMetadata(400));
        public static readonly DependencyProperty DisabledCuesVisibilityProperty = DependencyProperty.Register("DisabledCuesVisibility", typeof(Visibility), typeof(TreeView), new PropertyMetadata(Visibility.Visible));
        public static readonly DependencyProperty EditTemplateProperty = DependencyProperty.Register("EditTemplate", typeof(DataTemplate), typeof(TreeView), null);
        public static readonly DependencyProperty ExpandModeProperty = DependencyProperty.Register("ExpandMode", typeof(ExpandMode), typeof(TreeView), new PropertyMetadata(ExpandMode.Multiple, new PropertyChangedCallback(TreeView.OnExpandModePropertyChanged)));
        public static readonly DependencyProperty ExpandOnClickProperty = DependencyProperty.Register("ExpandOnClick", typeof(bool), typeof(TreeView), null);
        public static readonly DependencyProperty FocusCuesVisibilityProperty = DependencyProperty.Register("FocusCuesVisibility", typeof(Visibility), typeof(TreeView), new PropertyMetadata(Visibility.Visible));
        public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.Register("IsFocused", typeof(bool), typeof(TreeView), new PropertyMetadata(new PropertyChangedCallback(TreeView.OnIsFocusedPropertyChanged)));
        public static readonly DependencyProperty KeyboardNavigationProperty = DependencyProperty.Register("KeyboardNavigation", typeof(bool), typeof(TreeView), new PropertyMetadata(true));
        public static readonly DependencyProperty LineDashArrayProperty = DependencyProperty.Register("LineDashArray", typeof(DoubleCollection), typeof(TreeView), new PropertyMetadata(null));
        public static readonly DependencyProperty LineStrokeProperty = DependencyProperty.Register("LineStroke", typeof(Brush), typeof(TreeView), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
        public static readonly DependencyProperty LineThicknessProperty = DependencyProperty.Register("LineThickness", typeof(double), typeof(TreeView), new PropertyMetadata(1.0));
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(TreeView), null);
        public static readonly DependencyProperty ScrollBarStyleProperty = DependencyProperty.Register("ScrollBarStyle", typeof(Style), typeof(TreeView), null);
        internal const string ScrollElementName = "Scroll";
        public static readonly DependencyProperty SelectedBackgroundProperty = DependencyProperty.Register("SelectedBackground", typeof(Brush), typeof(TreeView), null);
        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(TreeViewItem), typeof(TreeView), null);
        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IList<TreeViewItem>), typeof(TreeView), null);
        public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register("SelectionMode", typeof(SelectionMode), typeof(TreeView), new PropertyMetadata(SelectionMode.Single, new PropertyChangedCallback(TreeView.OnSelectionModePropertyChanged)));
        public static readonly DependencyProperty ShowLinesProperty = DependencyProperty.Register("ShowLines", typeof(bool), typeof(TreeView), new PropertyMetadata(false));
        public static readonly DependencyProperty ValidationDecoratorStyleProperty = DependencyProperty.Register("ValidationDecoratorStyle", typeof(Style), typeof(TreeView), null);

        // Events
        public event DragDropEventHandler DragDrop;
        public event DragDropEventHandler DragOver;
        public event DragDropEventHandler DragStart;
        public event EventHandler<SourcedEventArgs> ItemClick;
        public event EventHandler<SourcedEventArgs> ItemCollapsed;
        public event EventHandler<SourcedEventArgs> ItemCollapsing;
        public event EventHandler<SourcedEventArgs> ItemExpanded;
        public event EventHandler<SourcedEventArgs> ItemExpanding;
        public event SelectionChangedEventHandler SelectionChanged;
        public event EventHandler<PropertyChangedEventArgs<SelectionMode>> SelectionModeChanged;

        // Methods
        public TreeView()
        {
            RoutedEventHandler handler = null;
            this._searchBuffer = string.Empty;
            this._throwSelectionModeChanged = true;
            base.DefaultStyleKey = typeof(TreeView);
            if (handler == null)
            {
                handler = (param0, param1) => this.ChangeVisualStateFocus(false);
            }
            base.Loaded += handler;
            base.GotFocus += new RoutedEventHandler(this.Control_GotFocus);
            base.LostFocus += new RoutedEventHandler(this.Control_LostFocus);
            this.SetCustomDefaultValues();
        }

        private void _selectionManager_SelectionChanged(object sender, SelectionChangedEventArgs<int> e)
        {
            this.FinishEditing(false, false);
            IList removedItems = new List<TreeViewItem>(this.SelectedItems);
            IList addedItems = new List<TreeViewItem>();
            this.SelectedItems.Clear();
            foreach (int num in this._selectionManager.SelectedItems)
            {
                if (!((List<TreeViewItem>)removedItems).Remove(this._itemList[num]))
                {
                    this._itemList[num].IsSelected = true;
                    addedItems.Add(this._itemList[num]);
                }
                this.SelectedItems.Add(this._itemList[num]);
            }
            foreach (TreeViewItem item in removedItems)
            {
                item.IsSelected = false;
            }
            this.SelectedItem = this._selectionManager.SelectedItem.HasValue ? this._itemList[this._selectionManager.SelectedItem.Value] : null;
            if (this.SelectedItem != null)
            {
                this.SelectedItem.EnsureVisible();
            }
            if (this.SelectionChanged != null)
            {
                this.SelectionChanged(this, new SelectionChangedEventArgs(removedItems, addedItems));
            }
        }

        private void Control_GotFocus(object sender, RoutedEventArgs e)
        {
            this.IsFocused = true;
        }

        private void Control_LostFocus(object sender, RoutedEventArgs e)
        {
            this.IsFocused = false;
        }

        protected void ChangeVisualStateFocus(bool useTransitions)
        {
            if (!this.IsFocused)
            {
                VisualStateHelper.GoToState(this, "Unfocused", useTransitions);
            }
            if (this.IsFocused)
            {
                VisualStateHelper.GoToState(this, "Focused", useTransitions);
            }
        }

        protected override void ClearContainerForItemOverride(DependencyObject element, object item)
        {
            base.ClearContainerForItemOverride(element, item);
            this.UnregisterDragSource(element as TreeViewItem);
            this.ClearSelection(element);
        }

        internal void ClearSelection()
        {
            if (!this._isProcessingSelection)
            {
                this._isProcessingSelection = true;
                this._selectionManager.ClearSelection();
                this._isProcessingSelection = false;
            }
        }

        internal void ClearSelection(object item)
        {
            if (!this._isProcessingSelection)
            {
                this._isProcessingSelection = true;
                TreeViewItem item2 = item as TreeViewItem;
                if ((item2 != null) && this.SelectedItems.Contains(item2))
                {
                    this._selectionManager.ClearSelection();
                }
                this._isProcessingSelection = false;
            }
        }

        private void CollapseBranches(TreeViewItem itemToExpand)
        {
            if (this.ExpandMode == ExpandMode.Single)
            {
                this._isUpdatingExpandedItems = true;
                List<WeakReference> list = this._expandedItems.ToList<WeakReference>();
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i].IsAlive)
                    {
                        TreeViewItem target = (TreeViewItem)list[i].Target;
                        if (!target.IsAncestorOf(itemToExpand))
                        {
                            ((TreeViewItem)list[i].Target).IsExpanded = false;
                            this._expandedItems.Remove(list[i]);
                        }
                    }
                }
                this._isUpdatingExpandedItems = false;
            }
        }

        private bool CompareItem(HierarchicalPresenter item, object text)
        {
            string str = (base.ItemConverter == null) ? item.ToString() : base.ItemConverter.ConvertToString(item);
            return (str.CompareTo(text) == 0);
        }

        public TreeViewItem FindItem(string text)
        {
            return (base.First(new Func<HierarchicalPresenter, object, bool>(this.CompareItem), text, this) as TreeViewItem);
        }

        public void FinishEditing()
        {
            this.FinishEditing(false, true);
        }

        public void FinishEditing(bool cancel, bool focusElement)
        {
            if (this._currentEditItem != null)
            {
                this._currentEditItem.FinishEditing(cancel);
                if (focusElement)
                {
                    this._currentEditItem.Focus();
                }
                this._currentEditItem = null;
            }
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new TreeViewItem();
        }

        private TreeViewItem GetFirstNode(bool visible)
        {
            TreeViewItem container = (TreeViewItem)base.GetContainer(base.Items[0]);
            while ((container != null) && (!container.IsEnabled || (visible && (container.Visibility != Visibility.Visible))))
            {
                container = visible ? container.NextVisibleNode : container.NextNode;
            }
            return container;
        }

        private string GetHeaderText(TreeViewItem item)
        {
            return base.ItemConverter.ConvertToString(item);
        }

        private DataTemplate GetItemDataTemplate(TreeViewItem tItem, object dataItem)
        {
            DataTemplate itemTemplate = null;
            if (base.ItemTemplateSelector != null)
            {
                itemTemplate = base.ItemTemplateSelector.SelectTemplate(dataItem, tItem);
            }
            if (base.ItemTemplate != null)
            {
                itemTemplate = base.ItemTemplate;
            }
            return itemTemplate;
        }

        private ItemPosition GetItemPositionFromIndex(int itemIndex)
        {
            ItemPosition normal = ItemPosition.Normal;
            if (base.Items.Count == 1)
            {
                return ItemPosition.Exclusive;
            }
            if (itemIndex == 0)
            {
                return ItemPosition.Root;
            }
            if (itemIndex == (base.Items.Count - 1))
            {
                normal = ItemPosition.Last;
            }
            return normal;
        }

        private ItemPosition GetItemPositionFromItem(object item)
        {
            return this.GetItemPositionFromIndex(base.Items.IndexOf(item));
        }

        public TreeViewItem GetNode(Point position)
        {
            return this.GetNode(null, this, position);
        }

        private TreeViewItem GetNode(TreeViewItem nearest, HierarchicalPresenter currentNode, Point position)
        {
            TreeViewItem item = nearest;
            try
            {
                foreach (object obj2 in currentNode.Items)
                {
                    UIElement visual = this.GetRootVisual();
                    TreeViewItem container = (TreeViewItem)currentNode.GetContainer(obj2);
                    Point point2 = new Point();
                    Point point = container.TransformToVisual(visual).Transform(point2);
                    double num = position.Y - point.Y;
                    if (num <= 0.0)
                    {
                        return item;
                    }
                    item = container;
                    if (container.IsExpanded && (container.Items.Count > 0))
                    {
                        item = this.GetNode(item, container, position);
                    }
                }
                return item;
            }
            catch
            {
            }
            return item;
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void HandleDragDrop(object source, DragDropEventArgs e)
        {
            if ((this.DragDrop.GetInvocationList().Length == 1) && (e.Effect != DragDropEffect.None))
            {
                TreeViewItem dragSource = e.DragSource as TreeViewItem;
                if (dragSource != null)
                {
                    TreeViewItem node = this.GetNode(e.GetPosition(null));
                    if (node != null)
                    {
                        int index = dragSource.Index;
                        int num2 = node.Index;
                        IList items = dragSource.ParentPresenter.Items;
                        if (dragSource.ParentPresenter.ItemsSource != null)
                        {
                            items = dragSource.ParentPresenter.ItemsSource as IList;
                        }
                        IList itemsSource = node.ParentPresenter.Items;
                        if (node.ParentPresenter.ItemsSource != null)
                        {
                            itemsSource = node.ParentPresenter.ItemsSource as IList;
                        }
                        if (this._isAppendAction)
                        {
                            itemsSource = node.Items;
                            if (node.ItemsSource != null)
                            {
                                itemsSource = node.ItemsSource as IList;
                            }
                            num2 = 0;
                        }
                        else
                        {
                            if (e.GetPosition(node).Y > (node.RenderSize.Height / 2.0))
                            {
                                num2++;
                            }
                            if ((items == itemsSource) && (index < num2))
                            {
                                num2--;
                            }
                        }
                        if (((items != null) && (itemsSource != null)) && (!items.IsReadOnly && !itemsSource.IsReadOnly))
                        {
                            object obj2 = (items.IndexOf(dragSource) == -1) ? dragSource.Header : dragSource;
                            items.Remove(obj2);
                            itemsSource.Insert(num2, obj2);
                        }
                    }
                }
            }
        }

        private void HandleDragOver(object source, DragDropEventArgs e)
        {
            if (this.DragOver.GetInvocationList().Length == 1)
            {
                this._dropLine.Visibility = Visibility.Collapsed;
                this._dropArrow.Visibility = Visibility.Collapsed;
                e.Effect = DragDropEffect.None;
                this._isAppendAction = false;
                TreeViewItem node = this.GetNode(e.GetPosition(null));
                if ((node != null) && this.IsValidTarget(e.DragSource as HierarchicalPresenter, node))
                {
                    Point point = node.TransformToVisual(this._dragDropManager.Canvas).Transform(new Point());
                    Point position = e.GetPosition(node);
                    double num = node.RenderSize.Height / 4.0;
                    FrameworkElement element = this._dropLine;
                    if ((position.Y > num) && (position.Y < (num * 3.0)))
                    {
                        element = this._dropArrow;
                        point.Y += num * 2.0;
                        this._isAppendAction = true;
                    }
                    else if (position.Y >= (num * 3.0))
                    {
                        point.Y += node.RenderSize.Height;
                    }
                    point.Y -= element.RenderSize.Height / 2.0;
                    element.SetValue(Canvas.LeftProperty, point.X);
                    element.SetValue(Canvas.TopProperty, point.Y);
                    element.Visibility = Visibility.Visible;
                    e.Effect = DragDropEffect.Move;
                }
            }
        }

        private void HandleKey(KeyEventArgs e)
        {
            if (!this.KeyboardNavigation)
            {
                return;
            }
            TreeViewItem selectedItem = this.SelectedItem;
            bool flag = false;
            if (selectedItem == null)
            {
                return;
            }
            switch (e.Key)
            {
                case Key.Enter:
                    this.FinishEditing(false, true);
                    flag = true;
                    goto Label_01F6;

                case Key.Shift:
                case Key.Ctrl:
                case Key.Alt:
                case Key.CapsLock:
                case Key.Space:
                    return;

                case Key.Escape:
                    this.FinishEditing(true, true);
                    flag = true;
                    goto Label_01F6;

                case Key.PageUp:
                case Key.PageDown:
                    {
                        double height = selectedItem.Bounds.Height;
                        double viewportHeight = this._elementScroll.ViewportHeight;
                        while (true)
                        {
                            TreeViewItem item4 = (e.Key == Key.PageUp) ? selectedItem.PrevVisibleNode : selectedItem.NextVisibleNode;
                            if ((item4 == null) || ((height + item4.Bounds.Height) > viewportHeight))
                            {
                                flag = true;
                                goto Label_01F6;
                            }
                            height += item4.Bounds.Height;
                            selectedItem = item4;
                        }
                    }
                case Key.End:
                    for (TreeViewItem item3 = selectedItem.NextVisibleNode; item3 != null; item3 = item3.NextVisibleNode)
                    {
                        selectedItem = item3;
                    }
                    flag = true;
                    goto Label_01F6;

                case Key.Home:
                    for (TreeViewItem item2 = selectedItem.PrevVisibleNode; item2 != null; item2 = item2.PrevVisibleNode)
                    {
                        selectedItem = item2;
                    }
                    flag = true;
                    goto Label_01F6;

                case Key.Left:
                    if (!selectedItem.IsExpanded)
                    {
                        selectedItem = selectedItem.ParentItem;
                    }
                    else
                    {
                        selectedItem.Collapse();
                        selectedItem = null;
                    }
                    flag = true;
                    goto Label_01F6;

                case Key.Up:
                    selectedItem = selectedItem.PrevVisibleNode;
                    flag = true;
                    goto Label_01F6;

                case Key.Right:
                    if (selectedItem.IsExpanded || (selectedItem.Items.Count <= 0))
                    {
                        selectedItem = selectedItem.NextVisibleNode;
                        break;
                    }
                    selectedItem.Expand();
                    selectedItem = null;
                    break;

                case Key.Down:
                    selectedItem = selectedItem.NextVisibleNode;
                    flag = true;
                    goto Label_01F6;

                case Key.F2:
                    this.StartEditing(selectedItem);
                    flag = true;
                    goto Label_01F6;

                case Key.Add:
                    if (!selectedItem.IsExpanded && (selectedItem.Items.Count > 0))
                    {
                        selectedItem.Expand();
                        selectedItem = null;
                    }
                    flag = true;
                    goto Label_01F6;

                case Key.Subtract:
                    if (selectedItem.IsExpanded)
                    {
                        selectedItem.Collapse();
                        selectedItem = null;
                    }
                    flag = true;
                    goto Label_01F6;

                default:
                    return;
            }
            flag = true;
        Label_01F6:
            if (selectedItem != null)
            {
                selectedItem.IsSelected = true;
            }
            e.Handled = flag;
        }

        internal void HandleSelectionChange(TreeViewItem item)
        {
            this.HandleSelectionChange(item, true);
        }

        internal void HandleSelectionChange(TreeViewItem item, bool isSelected)
        {
            if (!this._isProcessingSelection)
            {
                this._isProcessingSelection = true;
                this._itemList = base.ToList<TreeViewItem>();
                if ((this._itemList.Count > 0) && (this._itemList.IndexOf(item) >= 0))
                {
                    this._selectionManager.HandleSelectionChange(this._itemList.IndexOf(item), isSelected);
                }
                this._isProcessingSelection = false;
            }
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return (item is TreeViewItem);
        }

        private bool IsValidTarget(HierarchicalPresenter source, HierarchicalPresenter target)
        {
            if ((source == null) || (target == null))
            {
                return false;
            }
            return (!source.IsAncestorOf(target) && (source != target));
        }

        private void OnAfterApplyTemplate()
        {
            this._dropLine = base.GetTemplateChild("DropLine") as FrameworkElement;
            this._dropArrow = base.GetTemplateChild("DropArrow") as FrameworkElement;
            if (this._dropLine != null)
            {
                this._dropLine.RemoveFromParent();
                this._dragDropManager.Canvas.Children.Add(this._dropLine);
            }
            if (this._dropArrow != null)
            {
                this._dropArrow.RemoveFromParent();
                this._dragDropManager.Canvas.Children.Add(this._dropArrow);
            }
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementScroll = this.GetTemplateChild<System.Windows.Controls.ScrollViewer>("Scroll", true, ref errors);
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to TreeView.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.ChangeVisualStateFocus(false);
                this.OnAfterApplyTemplate();
            }
        }

        protected override AutomationPeer OnCreateAutomationPeer()
        {
            if (this._peer == null)
            {
                this._peer = AutomationPeerFactory.CreateAutomationPeer(this, typeof(TreeView));
            }
            if (this._peer == null)
            {
                return base.OnCreateAutomationPeer();
            }
            return this._peer;
        }

        protected virtual void OnDragDrop(object source, DragDropEventArgs e)
        {
            if (!this.AllowDragDrop)
            {
                e.Effect = DragDropEffect.None;
            }
            else if (this.DragDrop != null)
            {
                this.DragDrop(source, e);
            }
        }

        protected virtual void OnDragOver(object source, DragDropEventArgs e)
        {
            if (!this.AllowDragDrop)
            {
                e.Effect = DragDropEffect.None;
            }
            else if (this.DragOver != null)
            {
                this.DragOver(source, e);
            }
        }

        protected virtual void OnDragStart(object source, DragDropEventArgs e)
        {
            if (!this.AllowDragDrop)
            {
                e.Effect = DragDropEffect.None;
            }
            else if (this.DragStart != null)
            {
                this.DragStart(source, e);
            }
        }

        private void OnExpandModeChanged(ExpandMode oldValue)
        {
            if (this.ExpandMode == ExpandMode.Multiple)
            {
                this._expandedItems.Clear();
            }
        }

        private static void OnExpandModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TreeView view = d as TreeView;
            ExpandMode oldValue = (ExpandMode)e.OldValue;
            view.OnExpandModeChanged(oldValue);
        }

        private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as TreeView).ChangeVisualStateFocus(true);
        }

        protected internal virtual void OnItemClick(SourcedEventArgs e)
        {
            if (this.ItemClick != null)
            {
                this.ItemClick(this, e);
            }
        }

        protected internal virtual void OnItemCollapsed(SourcedEventArgs e)
        {
            if (this.ItemCollapsed != null)
            {
                this.ItemCollapsed(this, e);
            }
        }

        protected internal virtual void OnItemCollapsing(SourcedEventArgs e)
        {
            if (this.ItemCollapsing != null)
            {
                this.ItemCollapsing(this, e);
            }
        }

        protected internal virtual void OnItemExpanded(SourcedEventArgs e)
        {
            if (this.ItemExpanded != null)
            {
                this.ItemExpanded(this, e);
            }
        }

        protected internal virtual void OnItemExpanding(SourcedEventArgs e)
        {
            if (this.ItemExpanding != null)
            {
                this.ItemExpanding(this, e);
            }
        }

        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
            if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                for (int i = 0; i < base.Items.Count; i++)
                {
                    TreeViewItem item = this.TreeViewItemFromIndex(i);
                    if (item != null)
                    {
                        item.Position = this.GetItemPositionFromIndex(i);
                    }
                }
            }
            if (e.NewItems != null)
            {
                foreach (object obj2 in e.NewItems)
                {
                    HierarchicalPresenter presenter = obj2 as HierarchicalPresenter;
                    if (presenter != null)
                    {
                        presenter.InitializePresenter(this, this);
                    }
                }
            }
            if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                this.ClearSelection();
            }
        }

        internal void OnKeyDown(KeyEventArgs e)
        {
            if (!KeyboardUtil.Ctrl && !KeyboardUtil.Shift)
            {
                if (this.AutoSearch && (this._currentEditItem == null))
                {
                    long ticks = DateTime.Now.Ticks;
                    TimeSpan span = new TimeSpan(ticks - this._lastKeyTicks);
                    this._lastKeyTicks = ticks;
                    if (span.TotalMilliseconds >= this.AutoSearchResetDelay)
                    {
                        this._searchBuffer = string.Empty;
                    }
                    string keyString = KeyboardUtil.GetKeyString(e);
                    if (((keyString != null) && (e.Key != Key.Add)) && (e.Key != Key.Subtract))
                    {
                        this._searchBuffer = this._searchBuffer + keyString;
                        if (!this.PerformAutoSearch(this._searchBuffer))
                        {
                            this._searchBuffer = string.Empty;
                        }
                        e.Handled = true;
                        return;
                    }
                }
                this.HandleKey(e);
            }
        }

        private void OnSelectionModeChanged(object sender, PropertyChangedEventArgs<SelectionMode> e)
        {
            this._selectionManager.SelectionMode = this.SelectionMode;
            this.FinishEditing(false, false);
        }

        private static void OnSelectionModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TreeView sender = d as TreeView;
            if ((sender.SelectionModeChanged != null) && sender._throwSelectionModeChanged)
            {
                PropertyChangedEventArgs<SelectionMode> args = new PropertyChangedEventArgs<SelectionMode>
                {
                    OldValue = (SelectionMode)e.OldValue,
                    NewValue = (SelectionMode)e.NewValue
                };
                sender.SelectionModeChanged(sender, args);
            }
        }

        private bool PerformAutoSearch(string search)
        {
            TreeViewItem selectedItem = this.SelectedItem;
            TreeViewItem item = selectedItem;
            if (item != null)
            {
                if (search.Length == 1)
                {
                    item = item.NextVisibleNode;
                    if (item == null)
                    {
                        item = this.GetFirstNode(true);
                    }
                }
                while ((item != null) && (item != selectedItem))
                {
                    string str = (item.Header != null) ? this.GetHeaderText(item) : "";
                    if (!string.IsNullOrEmpty(str) && str.StartsWith(search, StringComparison.InvariantCultureIgnoreCase))
                    {
                        item.IsSelected = true;
                        return true;
                    }
                    item = item.NextVisibleNode;
                    if (item == null)
                    {
                        item = this.GetFirstNode(true);
                    }
                }
            }
            return false;
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            TreeViewItem item2 = element as TreeViewItem;
            this.RegisterDragSource(item2);
            FrameworkElement target = element as FrameworkElement;
            if (target != null)
            {
                if (item2 != item)
                {
                    DataTemplate itemDataTemplate = this.GetItemDataTemplate(item2, item);
                    if (itemDataTemplate is HierarchicalDataTemplate)
                    {
                        HierarchicalDataTemplate template2 = itemDataTemplate as HierarchicalDataTemplate;
                        item2.SetBinding(ItemsControl.ItemsSourceProperty, template2.ItemsSource);
                        if (template2.ItemTemplate == null)
                        {
                            item2.ItemTemplate = base.ItemTemplate;
                        }
                        else
                        {
                            item2.ItemTemplate = template2.ItemTemplate;
                        }
                    }
                }
                target.SetBinding<TreeView>(Control.FontFamilyProperty, this, tv => tv.FontFamily);
                target.SetBinding<TreeView>(Control.FontSizeProperty, this, tv => tv.FontSize);
                target.SetBinding<TreeView>(Control.FontStretchProperty, this, tv => tv.FontStretch);
                target.SetBinding<TreeView>(Control.FontStyleProperty, this, tv => tv.FontStyle);
                target.SetBinding<TreeView>(Control.FontWeightProperty, this, tv => tv.FontWeight);
                target.SetBinding<TreeView>(Control.ForegroundProperty, this, tv => tv.Foreground);
                target.SetBinding<TreeView>(TreeViewItem.SelectedBackgroundProperty, this, tv => tv.SelectedBackground);
                target.SetBinding<TreeView>(TreeViewItem.MouseOverBrushProperty, this, tv => tv.MouseOverBrush);
                target.SetBinding<TreeView>(TreeViewItem.EditTemplateProperty, this, tv => tv.EditTemplate);
                TreeViewItem item3 = target as TreeViewItem;
                if (item3 != null)
                {
                    item3.SetBinding<TreeView>(TreeViewItem.ShowLinesProperty, this, x => x.ShowLines);
                    item3.SetBinding<TreeView>(TreeViewItem.LineStrokeProperty, this, x => x.LineStroke);
                    item3.SetBinding<TreeView>(TreeViewItem.LineThicknessProperty, this, x => x.LineThickness);
                    item3.SetBinding<TreeView>(TreeViewItem.LineDashArrayProperty, this, x => x.LineDashArray);
                    item3.Position = this.GetItemPositionFromItem(item);
                    if ((item3.Position == ItemPosition.Last) && (base.Items.Count > 1))
                    {
                        this.TreeViewItemFromIndex(base.Items.Count - 2).Position = this.GetItemPositionFromIndex(base.Items.Count - 2);
                    }
                }
            }
        }

        internal void RegisterDragSource(TreeViewItem item)
        {
            if (item != null)
            {
                this._dragDropManager.RegisterDragSource(item, DragDropEffect.Move, ModifierKeys.None);
            }
        }

        internal void RegisterExpandedItem(TreeViewItem item)
        {
            if (this.ExpandMode == ExpandMode.Single)
            {
                this.CollapseBranches(item);
                this._expandedItems.Add(new WeakReference(item));
            }
        }

        private void SetAutoSearchResetDelayValue(int value)
        {
            base.SetValue(AutoSearchResetDelayProperty, Math.Max(0, value));
        }

        private void SetCustomDefaultValues()
        {
            base.IsTabStop = true;
            base.MouseEnter += (s, e) => base.ForceMouseOver = base.IsMouseOver = true;
            base.MouseLeave += (s, e) => base.ForceMouseOver = base.IsMouseOver = false;
            this._dragDropManager = new DragDropManager();
            this._dragDropManager.RegisterDropTarget(this, true);
            //this._dragDropManager.DragStart += new DragDropEventHandler(this.OnDragStart);
            this._dragDropManager.DragOver += new DragDropEventHandler(this.OnDragOver);
            this._dragDropManager.DragDrop += new DragDropEventHandler(this.OnDragDrop);
            this.DragOver += new DragDropEventHandler(this.HandleDragOver);
            this.DragDrop += new DragDropEventHandler(this.HandleDragDrop);
            this.SelectedItems = new List<TreeViewItem>();
            this.SelectionMode = SelectionMode.Single;
            this._selectionManager = new RangeSelectionManager();
            this._selectionManager.SelectionChanged += new EventHandler<SelectionChangedEventArgs<int>>(this._selectionManager_SelectionChanged);
            this.SelectionModeChanged += new EventHandler<PropertyChangedEventArgs<SelectionMode>>(this.OnSelectionModeChanged);
            this._expandedItems = new List<WeakReference>();
            base.InitializePresenter(this, null);
        }

        public void StartEditing()
        {
            this.StartEditing(this.SelectedItem);
        }

        public void StartEditing(TreeViewItem item)
        {
            this.FinishEditing(false, false);
            if ((this.EditTemplate != null) && (item != null))
            {
                this._currentEditItem = item;
                this._currentEditItem.StartEditing();
            }
        }

        private TreeViewItem TreeViewItemFromIndex(int index)
        {
            if ((index < base.Items.Count) && (index >= 0))
            {
                return this.TreeViewItemFromItem(base.Items[index]);
            }
            return null;
        }

        private TreeViewItem TreeViewItemFromItem(object item)
        {
            TreeViewItem item2 = item as TreeViewItem;
            if (item2 != null)
            {
                return item2;
            }
            return (TreeViewItem)base.ItemContainerGenerator.ContainerFromItem(item);
        }

        internal void UnregisterDragSource(TreeViewItem item)
        {
            if (item != null)
            {
                this._dragDropManager.RegisterDragSource(item, DragDropEffect.None, ModifierKeys.None);
            }
        }

        internal void UnRegisterExpandedItem(TreeViewItem item)
        {
            if ((this.ExpandMode == ExpandMode.Single) && !this._isUpdatingExpandedItems)
            {
                for (int i = 0; i < this._expandedItems.Count; i++)
                {
                    if (this._expandedItems[i].IsAlive && (this._expandedItems[i].Target == item))
                    {
                        this._expandedItems.RemoveAt(i);
                        return;
                    }
                }
            }
        }

        // Properties
        public bool AllowDragDrop
        {
            get { return (bool)GetValue(AllowDragDropProperty); }
            set { SetValue(AllowDragDropProperty, value); }
        }

        public AutoScrollMode AutoScrollMode
        {
            get { return (AutoScrollMode)GetValue(AutoScrollModeProperty); }
            set { SetValue(AutoScrollModeProperty, value); }
        }

        public bool AutoSearch
        {
            get { return (bool)GetValue(AutoSearchProperty); }
            set { SetValue(AutoSearchProperty, value); }
        }

        public int AutoSearchResetDelay
        {
            get { return (int)GetValue(AutoSearchResetDelayProperty); }
            set { SetValue(AutoSearchResetDelayProperty, value); }
        }

        public Visibility DisabledCuesVisibility
        {
            get { return (Visibility)GetValue(DisabledCuesVisibilityProperty); }
            set { SetValue(DisabledCuesVisibilityProperty, value); }
        }

        public FrameworkElement DragDropArrowMarker
        {
            get { return this._dropArrow; }
        }

        public FrameworkElement DragDropLineMarker
        {
            get { return this._dropLine; }
        }

        public DataTemplate EditTemplate
        {
            get { return (DataTemplate)GetValue(EditTemplateProperty); }
            set { SetValue(EditTemplateProperty, value); }
        }

        public ExpandMode ExpandMode
        {
            get { return (ExpandMode)GetValue(ExpandModeProperty); }
            set { SetValue(ExpandModeProperty, value); }
        }

        public bool ExpandOnClick
        {
            get { return (bool)GetValue(ExpandOnClickProperty); }
            set { SetValue(ExpandOnClickProperty, value); }
        }

        public Visibility FocusCuesVisibility
        {
            get { return (Visibility)GetValue(FocusCuesVisibilityProperty); }
            set { SetValue(FocusCuesVisibilityProperty, value); }
        }

        public bool IsFocused
        {
            get { return (bool)GetValue(IsFocusedProperty); }
            internal set { SetValue(IsFocusedProperty, value); }
        }

        public bool KeyboardNavigation
        {
            get { return (bool)GetValue(KeyboardNavigationProperty); }
            set { SetValue(KeyboardNavigationProperty, value); }
        }

        public DoubleCollection LineDashArray
        {
            get { return (DoubleCollection)GetValue(LineDashArrayProperty); }
            set { SetValue(LineDashArrayProperty, value); }
        }

        public Brush LineStroke
        {
            get { return (Brush)GetValue(LineStrokeProperty); }
            set { SetValue(LineStrokeProperty, value); }
        }

        public double LineThickness
        {
            get { return (double)GetValue(LineThicknessProperty); }
            set { SetValue(LineThicknessProperty, value); }
        }

        public Brush MouseOverBrush
        {
            get { return (Brush)GetValue(MouseOverBrushProperty); }
            set { SetValue(MouseOverBrushProperty, value); }
        }

        public Style ScrollBarStyle
        {
            get { return (Style)GetValue(ScrollBarStyleProperty); }
            set { SetValue(ScrollBarStyleProperty, value); }
        }

        internal System.Windows.Controls.ScrollViewer ScrollViewer
        {
            get { return this._elementScroll; }
        }

        public Brush SelectedBackground
        {
            get { return (Brush)GetValue(SelectedBackgroundProperty); }
            set { SetValue(SelectedBackgroundProperty, value); }
        }

        public TreeViewItem SelectedItem
        {
            get { return (TreeViewItem)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public IList<TreeViewItem> SelectedItems
        {
            get { return (IList<TreeViewItem>)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

        public SelectionMode SelectionMode
        {
            get { return (SelectionMode)GetValue(SelectionModeProperty); }
            set { SetValue(SelectionModeProperty, value); }
        }

        public bool ShowLines
        {
            get { return (bool)GetValue(ShowLinesProperty); }
            set { SetValue(ShowLinesProperty, value); }
        }

        public Style ValidationDecoratorStyle
        {
            get { return (Style)GetValue(ValidationDecoratorStyleProperty); }
            set { SetValue(ValidationDecoratorStyleProperty, value); }
        }
    }

    public enum AutoScrollMode
    {
        Vertical,
        Both,
        None
    }

    public enum ExpandMode
    {
        Single,
        Multiple
    }
}
